home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / xinetd.2 / xinetd / xinetd.2.1.7-linux.4 / libs / src / timer / timer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-25  |  5.4 KB  |  273 lines

  1. /*
  2.  * (c) Copyright 1993 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: timer.c,v 4.2 1993/05/06 06:43:14 panos Exp $" ;
  8. static char *version = VERSION ;
  9.  
  10. #include "timemacros.h"
  11. #include "impl.h"
  12. #include "defs.h"
  13.  
  14. #define TIMER_H_NULL                    ((timer_h)NULL)
  15.  
  16.  
  17. int timer_errno ;
  18.  
  19.  
  20.  
  21. /*
  22.  * Create a timer of the specified type.
  23.  * Returns a timer handle
  24.  */
  25. timer_h timer_create( type, flags, errnop )
  26.     enum timer_types    type ;
  27.     int                    flags ;
  28.     int                    *errnop ;
  29. {
  30.     int        *errp = ( errnop != NULL ) ? errnop : &timer_errno ;
  31.     timer_s    *tp ;
  32.  
  33.     if ( type != TIMER_REAL && type != TIMER_VIRTUAL && type != TIMER_PROF )
  34.             HANDLE_ERROR( flags, TIMER_H_NULL, errp, TIMER_EBADTYPE,
  35.                             "TIMER timer_create: bad timer type\n" ) ;
  36.             
  37.     tp = TIMER_ALLOC() ;
  38.     if ( tp == NULL )
  39.     {
  40.         *errp = TIMER_ENOMEM ;
  41.         return( TIMER_H_NULL ) ;
  42.     }
  43.     
  44.     tp->t_state = INACTIVE ;
  45.     tp->t_act = IDLE ;
  46.     tp->t_blocked = FALSE ;
  47.  
  48.     tp->t_errnop = errp ;
  49.     tp->t_flags = flags & TIMER_CREATE_FLAGS ;
  50.     tp->t_action.ta_func = NULL ;
  51.     tp->t_action.ta_arg = NULL ;
  52.     tp->t_action.ta_flags = TIMER_NOFLAGS ;
  53.     if ( __ostimer_newtimer( tp, type ) == TIMER_ERR )
  54.     {
  55.         TIMER_FREE( tp ) ;
  56.         return( TIMER_H_NULL ) ;
  57.     }
  58.     return( (timer_h) tp ) ;
  59. }
  60.  
  61.  
  62. void timer_destroy( handle )
  63.     timer_h    handle ;
  64. {
  65.     timer_s    *tp = TP( handle ) ;
  66.  
  67.     __ostimer_blockall() ;
  68.  
  69.     if ( tp->t_state == TICKING )
  70.     {
  71.         __ostimer_remove( tp->t_ostimer, tp ) ;
  72.         tp->t_state = DESTROYED ;
  73.     }
  74.     
  75.     if ( tp->t_act == IDLE || tp->t_act == PENDING )
  76.         TIMER_FREE( tp ) ;
  77.  
  78.     __ostimer_unblockall() ;
  79. }
  80.  
  81.  
  82. int timer_start( handle, itvp, time_type, ap )
  83.     timer_h                    handle ;
  84.     struct itimerval        *itvp ;
  85.     enum timer_timetypes time_type ;
  86.     struct timer_action    *ap ;
  87. {
  88.     int                    result ;
  89.     int                    ok_to_start ;
  90.     timer_s                *tp    = TP( handle ) ;
  91.     struct os_timer    *otp    = tp->t_ostimer ;
  92.  
  93.     __ostimer_blockall() ;
  94.  
  95.     /*
  96.      * We allow invoking timer_start from within the user-specified action
  97.      * after the timer has expired. However, we do not allow this for
  98.      * timers that have a t_interval (these timers stay at the TICKING state).
  99.      */
  100.     ok_to_start = tp->t_state == INACTIVE &&
  101.                             ( tp->t_act == IDLE || tp->t_act == INVOKED ) ;
  102.  
  103.     if ( ! ok_to_start )
  104.     {
  105.         __ostimer_unblockall() ;
  106.         HANDLE_ERROR( tp->t_flags, TIMER_ERR, tp->t_errnop, TIMER_EBADSTATE,
  107.             "TIMER timer_start: timer state does not allow this operation\n" ) ;
  108.     }
  109.  
  110.     if ( itvp->it_value.tv_sec < 0 || itvp->it_value.tv_usec < 0 )
  111.     {
  112.         __ostimer_unblockall() ;
  113.         HANDLE_ERROR( tp->t_flags, TIMER_ERR, tp->t_errnop, TIMER_EBADTIME,
  114.             "TIMER timer_start: neg time value)\n" ) ;
  115.     }
  116.  
  117.     tp->t_action = *ap ;
  118.     tp->t_action.ta_flags &= TIMER_START_FLAGS ;
  119.  
  120.     result = __ostimer_add( otp, tp, itvp, time_type ) ;
  121.     __ostimer_unblockall() ;
  122.     return( result ) ;
  123. }
  124.  
  125.  
  126. void timer_stop( handle )
  127.     timer_h handle ;
  128. {
  129.     timer_s *tp = TP( handle ) ;
  130.  
  131.     __ostimer_blockall() ;
  132.  
  133.     if ( tp->t_state == TICKING )
  134.     {
  135.         __ostimer_remove( tp->t_ostimer, tp ) ;
  136.         tp->t_state = INACTIVE ;
  137.     }
  138.  
  139.     if ( tp->t_act == SCHEDULED )
  140.         tp->t_act = INVOKED ;        /* to avoid the invocation */
  141.     else if ( tp->t_act == PENDING )
  142.         tp->t_act = IDLE ;
  143.  
  144.     tp->t_blocked = FALSE ;
  145.     
  146.     __ostimer_unblockall() ;
  147. }
  148.  
  149.  
  150. void timer_block( handle )
  151.     timer_h handle ;
  152. {
  153.     timer_s *tp = TP( handle ) ;
  154.  
  155.     __ostimer_blockall() ;
  156.  
  157.     if ( tp->t_state == TICKING || 
  158.             tp->t_state == INACTIVE && 
  159.                 ( tp->t_act == PENDING || tp->t_act == SCHEDULED ) )
  160.         tp->t_blocked = TRUE ;
  161.  
  162.     __ostimer_unblockall() ;
  163. }
  164.  
  165.  
  166. void timer_unblock( handle )
  167.     timer_h handle ;
  168. {
  169.     timer_s *tp = TP( handle ) ;
  170.  
  171.     __ostimer_blockall() ;
  172.  
  173.     if ( tp->t_blocked )
  174.     {
  175.         tp->t_blocked = FALSE ;
  176.         if ( tp->t_act == PENDING )
  177.         {
  178.             tp->t_act = SCHEDULED ;
  179.             (void) __timer_invoke( tp ) ;
  180.         }
  181.     }
  182.     
  183.     __ostimer_unblockall() ;
  184. }
  185.  
  186.  
  187. unsigned timer_expirations( handle )
  188.     timer_h handle ;
  189. {
  190.     return( TP( handle )->t_count ) ;
  191. }
  192.  
  193.  
  194.  
  195. /*
  196.  * Invoke the action of the specified timer
  197.  * All timer interrupts should be blocked when this function is invoked
  198.  * Returns TRUE if 
  199.  */
  200. enum timer_state __timer_invoke( tp )
  201.     register timer_s *tp ;
  202. {
  203.     enum timer_state state ;
  204.  
  205.     /*
  206.      * The reason for the infinite loop is that the timer may reexpire
  207.      * while its function is being invoked.
  208.      */
  209.     for ( ;; )
  210.     {
  211.         /*
  212.          * This is the INVOKE part
  213.          */
  214.         if ( tp->t_blocked )
  215.             tp->t_act = PENDING ;
  216.         else
  217.         {
  218.             if ( tp->t_state != DESTROYED && tp->t_act == SCHEDULED )
  219.             {
  220.                 void    (*func)()    = tp->t_action.ta_func ;
  221.                 void    *arg            = tp->t_action.ta_arg ;
  222.                 int    flags         = tp->t_action.ta_flags ;
  223.  
  224.                 tp->t_act = INVOKED ;
  225.                 tp->t_expirations = tp->t_count ;
  226.                 tp->t_count = 0 ;
  227.                 if ( func != NULL )
  228.                 {
  229.                     int unblock_all_intrs = ! ( flags & TIMER_BLOCK_ALL ) ;
  230.                     int unblock_all_but_same_intr = ! ( flags & TIMER_BLOCK_SAME ) ;
  231.                     
  232.                     if ( unblock_all_intrs )
  233.                         __ostimer_unblockall() ;
  234.                     else if ( unblock_all_but_same_intr )
  235.                         __ostimer_unblockall_except( tp->t_ostimer ) ;
  236.  
  237.                     (*func)( tp, arg ) ;
  238.  
  239.                     if ( unblock_all_intrs || unblock_all_but_same_intr )
  240.                         __ostimer_blockall() ;
  241.                 }
  242.                 else if ( arg != NULL )
  243.                 {
  244.                     int *ip = (int *) arg ;
  245.  
  246.                     if ( flags & TIMER_INC_VAR )
  247.                         *ip += tp->t_expirations ;
  248.                     else
  249.                         *ip = 1 ;
  250.                 }
  251.             }
  252.         }
  253.  
  254.         state = tp->t_state ;
  255.  
  256.         /*
  257.          * This is the RETURN part
  258.          */
  259.         if ( tp->t_state == DESTROYED )
  260.             TIMER_FREE( tp ) ;
  261.         else
  262.         {
  263.             if ( tp->t_act == INVOKED )
  264.                 tp->t_act = IDLE ;
  265.             else if ( tp->t_act == SCHEDULED )
  266.                 continue ;
  267.         }
  268.         break ;
  269.     }
  270.     return( state ) ;
  271. }
  272.  
  273.